map地图坐标转换
Introduction
以前在接触微信定位时就考察过这方面的东西,但是现在看来,当初还是调研不够仔细。
总述
对于坐标系来说,国际上通用的坐标系为WGS-84
(World Geodetic System),而国内最基本的也要在此基础上进行一次加密,从而得到一个国内经常使用的坐标系GCJ-02
,这种地址也就是常说的火星地址。有些地图厂商为了数据更加安全,有对GCJ-02
加密了一次。例如:百度地图进行了BD-09
二次加密。下图说明了国内常用地图的坐标系:
微信开发中的有关坐标
微信消息发送的地址采用的是腾讯地图的坐标系;而在开发者模式中,微信服务器推送给开发者的位置事件中的地址是GPS定位的结果,需要转换成百度坐标系(或其他坐标系)才能使用。
这里提供几个在解决问题时遇到的好的工具
- GPS转谷歌百度地图经纬度及相应接口:http://map.yanue.net/gps.html
- 百度坐标拾取系统:http://api.map.baidu.com/lbsapi/getpoint/index.html
- 腾讯坐标拾取器:http://api.map.soso.com/doc_v2/tooles/picker.html
- 百度地图API示例:http://developer.baidu.com/map/jsdemo.htm#a1_2
坐标转化工具
首先有一个表示地点的类Point
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public static class Point {
private BigDecimal longitude;
private BigDecimal latitude;
public static Point getPoint(BigDecimal longitude, BigDecimal latitude) {
return new Point(longitude, latitude);
}
private Point(BigDecimal longitude, BigDecimal latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
public BigDecimal getLongitude() {
return longitude;
}
public BigDecimal getLatitude() {
return latitude;
}
}
百度转GCJ-021
2
3
4
5
6
7
8
9
10public static Point baiduToMars(Point point) {
double x = point.getLongitude().doubleValue() - 0.0065;
double y = point.getLatitude().doubleValue() - 0.006;
double xPi = x / 180.0;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * xPi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * xPi);
BigDecimal longitude = BigDecimal.valueOf(z * Math.cos(theta));
BigDecimal latitude = BigDecimal.valueOf(z * Math.sin(theta));
return Point.getPoint(longitude, latitude);
}
GCJ-02转百度1
2
3
4
5
6
7
8
9
10
11
12public static Point marsToBaidu(Point point) {
double xPi = 3.14159265358979324 * 3000.0 / 180.0;
double x = point.getLongitude().doubleValue();
double y = point.getLatitude().doubleValue();
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * xPi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * xPi);
x = z * Math.cos(theta) + 0.0065;
y = z * Math.sin(theta) + 0.006;
BigDecimal longitude = BigDecimal.valueOf(x);
BigDecimal latitude = BigDecimal.valueOf(y);
return Point.getPoint(longitude, latitude);
}
WGS-84转GCJ-021
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39public static class EvilTransform {//World Geodetic System to Mars Geodetic System
// Krasovsky 1940
static double pi = 3.14159265358979324;
static double a = 6378245.0;
static double ee = 0.00669342162296594323;
public static Point transform(Point point) {
double worldLongitude = point.getLongitude().doubleValue();
double worldLatitude = point.getLatitude().doubleValue();
double dLat = transformLatitude(worldLongitude - 105.0, worldLatitude - 35.0);
double dLon = transformLongitude(worldLongitude - 105.0, worldLatitude - 35.0);
double radLat = worldLatitude / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double marsLatitude = worldLatitude + dLat;
double marsLongitude = worldLongitude + dLon;
return new Point(BigDecimal.valueOf(marsLongitude), BigDecimal.valueOf(marsLatitude));
}
private static double transformLatitude(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
private static double transformLongitude(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
}
参考链接
- http://www.biaodianfu.com/coordinate-system.html
- https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#353936
- http://mp.weixin.qq.com/qa/index.php?qa=9465&qa_1=%E6%8E%A5%E6%94%B6%E7%9A%84%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE%E5%9C%A8%E4%B8%8D%E5%90%8C%E5%AE%B6%E5%9C%B0%E5%9B%BE%E4%B8%AD%E6%98%BE%E7%A4%BA%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%81%8F%E5%B7%AE%E5%BE%88%E5%A4%A7(2015-6-7 12:19:36该连接已经失效)
over